home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-03 | 14.3 KB | 462 lines | [TEXT/MPS ] |
- // UDependencies.h
- // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
-
- #ifndef __UDEPENDENCIES__
- #define __UDEPENDENCIES__
-
- // MacApp
-
- #ifndef __ULIST__
- #include "UList.h"
- #endif
-
- #ifndef __ULISTITERATOR__
- #include "UListIterator.h"
- #endif
-
- #ifndef __UOBJECT__
- #include "UObject.h"
- #endif
-
- // ANSI
-
- #ifndef __LIMITS__
- #include <limits.h>
- #endif
-
- //----------------------------------------------------------------------------------------
- /* Theory of Operation
- -------------------
-
- The dependency relationships are stored in two arrays of triples, where each
- triple contains a primary object, a secondary object and a label. The arrays are
- sorted first by the primary object.
-
- One array, gDependents, contains notifier-dependent relationships, so the primary
- object is a notifier and the secondary objects are dependents. For example,
- suppose A has two dependents C and D, each of which has B as a dependent.
- The dependents array looks as follows:
-
- A C label
- A D label
- C B label
- D B label
-
- The other array, gNotifiers, contains dependent-notifier relationships, so the
- primary object is a dependent and the secondary objects are notifiers:
-
- B C label
- B D label
- C A label
- D A label
-
- The labels are used for marking objects, though they may have other uses in future.
-
- Iteration over the secondary objects for a given primary object is performed by
- doing a binary search for a matching primary object, then iterating backwards to
- find the beginning of the cluster of entries with that primary object. Iteration then
- proceeds forwards until the primary object changes. To iterate over the dependents of
- an object we use gDependents, and to iterate over its notifiers we use gNotifiers.
-
- These data structures are not particularly space-efficient, but allow fast iteration
- over both notifiers and dependents. Each entry is only twelve bytes, so you should be
- able to have hundreds of dependencies with no problem.*/
-
- //----------------------------------------------------------------------------------------
-
-
- //----------------------------------------------------------------------------------------
- // Constants
- //----------------------------------------------------------------------------------------
-
- const long kNoLabel = LONG_MAX - 1;
-
-
- //----------------------------------------------------------------------------------------
- // Typedefs
- //----------------------------------------------------------------------------------------
-
- typedef long DependencyLabels;
- // The valid range of labels
-
- typedef long LabelRange;
- // Used internally because we flip the label's sign to mark an object
-
-
- //----------------------------------------------------------------------------------------
- // Notification
- //----------------------------------------------------------------------------------------
-
- struct Notification
- {
- inline Notification()
- { };
-
- inline Notification(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy) :
- fNotifier(notifier),
- fChange(theChange),
- fChangedBy(changedBy)
- { }
-
- TObject* fNotifier;
- TObject* fChangedBy;
- ChangeID fChange;
- };
-
- //----------------------------------------------------------------------------------------
- // TNotificationQueue
- //----------------------------------------------------------------------------------------
-
- class TNotificationQueue : public TDynamicArray
- {
- MA_DECLARE_CLASS;
-
- public:
-
- inline TNotificationQueue()
- { }
-
- virtual ~TNotificationQueue();
-
- inline void INotificationQueue()
- { IDynamicArray(1, sizeof(Notification)); }
- // Initialize the array
-
- //------------------------------------------------------------------------------------
- // Insertion and Deletion
- //------------------------------------------------------------------------------------
-
- inline void Queue(const Notification& item)
- { InsertElementsBefore(1, (void*) &item, 1); }
- // FIFO queue addition.(same as insertLast)
-
- Boolean Dequeue(Notification& item);
- // FIFO queue relief
-
- //------------------------------------------------------------------------------------
- // static member functions
- //------------------------------------------------------------------------------------
- public:
-
- static TNotificationQueue* NewNotificationQueue();
- // Utility function to create a new TNotificationQueue object.
-
- };
-
- //----------------------------------------------------------------------------------------
- // Dependency
- //----------------------------------------------------------------------------------------
-
- struct Dependency
- {
- inline Dependency(TObject* primaryObject,
- TObject* secondaryObject,
- LabelRange dependencyLabel) :
- fPrimaryObject(primaryObject),
- fSecondaryObject(secondaryObject),
- fLabel(dependencyLabel)
- { }
- // Constructor
-
- TObject* fPrimaryObject;
- TObject* fSecondaryObject;
- LabelRange fLabel;
- };
-
- typedef struct Dependency *DependencyPtr;
-
- //----------------------------------------------------------------------------------------
- // TDependencies: An array for storing the dependency relationships
- //----------------------------------------------------------------------------------------
-
- class TDependencies : public TSortedDynamicArray
- {
- MA_DECLARE_CLASS;
-
- public:
-
- inline TDependencies()
- { }
- // Empty constructor
-
- virtual ~TDependencies();
- // Destructor
-
- inline void IDependencies()
- { ISortedDynamicArray(1, sizeof(Dependency)); }
- // Initialize the array
-
-
- //------------------------------------------------------------------------------------
- // Insertion and Deletion
- //------------------------------------------------------------------------------------
-
- virtual void AddDependency(TObject* primaryObject,
- TObject* secondaryObject,
- DependencyLabels dependencyLabel);
- // Register an object ("secondaryObject") as dependent on the specified change in
- // another object ("primaryObject")
-
- virtual void InsertDependencyBefore(ArrayIndex index,
- TObject* primaryObject,
- TObject* secondaryObject,
- DependencyLabels dependencyLabel);
- // Add a dependency relation to the array
-
- virtual void RemoveDependency(TObject* primaryObject,
- TObject* secondaryObject,
- DependencyLabels dependencyLabel);
- // Remove a dependency relation from the array if it is present
-
-
- //------------------------------------------------------------------------------------
- // Searching
- //------------------------------------------------------------------------------------
-
- virtual CompareResult CompareElements(void* Element1, void* Element2);
- // Orders the elements of the array by the ordinal value of the notifier.
-
- virtual Boolean FindDependency(TObject* primaryObject,
- TObject* secondaryObject,
- DependencyLabels dependencyLabel,
- ArrayIndex& index);
- // Returns true if the specified dependency is in the array. The position of the
- // dependency is returned in "index". If the dependency is not present the
- // position at which it should be inserted is returned in "index"
-
- virtual Boolean FindPrimaryObject(TObject* primaryObject, ArrayIndex& index);
- // Returns true if a binary search for the specified primary object succeeds.
- // The index of the found entry is also returned.
-
- inline TObject* PrimaryObjectAt(ArrayIndex i)
- { return ((DependencyPtr)ComputeAddress(i))->fPrimaryObject; }
- // Returns the primary object at a given index
-
- inline TObject* SecondaryObjectAt(ArrayIndex i)
- { return ((DependencyPtr)ComputeAddress(i))->fSecondaryObject; }
- // Returns the secondary object at a given index
- };
-
- //----------------------------------------------------------------------------------------
- // TDependencySpace: Abstract Superclass of Dependency Spaces
- //----------------------------------------------------------------------------------------
-
- class TDependencySpace : public TObject
- {
- MA_DECLARE_CLASS;
-
- public:
- inline TDependencySpace()
- { }
- // Empty constructor
-
- virtual ~TDependencySpace();
- // Destructor
-
- inline void IDependencySpace()
- { IObject(); }
- // Initialization method for TDependencySpace
-
- virtual void AddDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel);
- // Register an object ("dependent") as a dependent of another object ("Notifier"),
- // with specified label (can be kNoLabel)
-
- virtual void RemoveDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel);
- // Remove the dependency relation if it is present
-
- virtual void RemoveDependencies(TObject* anObject);
- // Remove all dependencies containing the object, either as Notifier or dependent.
- // Called by TObject::Free.
-
- virtual void NotifierChanged(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy);
- // Notifies dependents of "notifier" that it has changed
-
- };
-
- //----------------------------------------------------------------------------------------
- // TSimpleDependencySpace: Used by MacApp to store dependency relationships and propagate
- // changes to immediate dependents. MacApp has a single global instance gMacAppDependencies
- //----------------------------------------------------------------------------------------
-
- class TSimpleDependencySpace : public TDependencySpace
- {
- MA_DECLARE_CLASS;
-
- public:
- TSimpleDependencySpace();
- // Constructor
-
- inline void ISimpleDependencySpace()
- { IDependencySpace(); }
- // Initialize this object
-
- virtual ~TSimpleDependencySpace();
- // Free this object
-
- virtual void AddDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel); // Override
- // Register an object ("dependent") as a dependent of another object ("Notifier"),
- // with specified label (can be kNoLabel)
-
- virtual void RemoveDependency(TObject* notifier,
- TObject* dependent,
- DependencyLabels dependencyLabel); // Override
- // Remove the dependency relation if it is present
-
-
- virtual void RemoveDependencies(TObject* anObject); // Override
- // Remove all dependencies containing the object, either as Notifier or dependent.
- // Called by TObject::Free.
-
- virtual void NotifierChanged(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy); // Override
- // Notifies direct dependents of "notifier" that it has changed
-
- //----------------------------------------------------------------------------------------
- // data members
- //----------------------------------------------------------------------------------------
- public:
-
- TDependencies* fDependents;
- TDependencies* fNotifiers;
- };
-
- //----------------------------------------------------------------------------------------
- // TStandardDependencySpace: Can be used to store dependency relationships and propagate
- // changes to immediate and indirect dependents.
- //----------------------------------------------------------------------------------------
-
- class TStandardDependencySpace : public TSimpleDependencySpace
- {
- MA_DECLARE_CLASS;
-
- public:
- TStandardDependencySpace();
- // Constructor
- virtual ~TStandardDependencySpace();
- // Destructor
-
- inline void IStandardDependencySpace()
- { ISimpleDependencySpace(); }
- // Initialize this object
-
- virtual void NotifierChanged(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy); // Override
- // Notifies direct and indirect dependents of "notifier" that it has changed
- // Handles nested calls to Changed.
-
- void NotifyDependents(TObject* notifier,
- ChangeID theChange,
- TObject* changedBy);
- // Notifies direct and indirect dependents of "notifier" that it has changed
- // Does not handle nested calls to Changed.
-
- virtual void MarkAllDependents(TObject* notifier, Boolean state);
- // Marks all the direct and indirect dependents of "notifier"
-
- virtual void MarkObject(TObject* anObject, Boolean state); // Override
- // Used to mark or unmark an object as needing updating. Used during a change/update
- // phase
-
- virtual Boolean IsObjectMarked(TObject* anObject); // Override
- // Returns true if the specified object is currently marked
-
- virtual void UpdateMarkedObjects(ChangeID theChange,
- TObject* changedObject,
- TObject* changedBy);
- // Updates all marked objects by calling HandleUpdate
-
- virtual void HandleUpdate(TObject* anObject,
- ChangeID theChange,
- TObject* changedObject,
- TObject* changedBy);
- // If "anObject" is marked as needing updating, unmark it, update all its notifiers,
- // then update the object itself by calling its DoUpdate method
-
- virtual void UpdateNotifiers(TObject* anObject,
- ChangeID theChange,
- TObject* changedObject,
- TObject* changedBy);
- // Recursively updates each notifier of "anObject"
-
- //----------------------------------------------------------------------------------------
- // data members
- //----------------------------------------------------------------------------------------
- public:
- TNotificationQueue* fNestedUpdates; // Queue of updates to be processed
- Boolean fUpdating; // An update is in progress
-
- };
-
- //----------------------------------------------------------------------------------------
- // Iterators
- //----------------------------------------------------------------------------------------
-
- class CDependencyIterator : public CArrayIterator {
- public:
- CDependencyIterator (TDependencies* theArray, TObject* theObject);
-
- virtual ~CDependencyIterator();
-
- void Reset(); // Override
-
- Boolean More(); // Override
-
- TObject* CurrentObject();
-
- TObject* FirstObject();
-
- TObject* NextObject();
-
- protected:
- TObject* fObject;
- };
-
- class CDependentIterator : public CDependencyIterator {
- public:
- CDependentIterator (TObject* theObject, TSimpleDependencySpace* dependencySpace);
-
- virtual ~CDependentIterator();
-
- inline TObject* FirstDependent()
- { return FirstObject(); }
-
- inline TObject* NextDependent()
- { return NextObject(); }
-
- inline TObject* CurrentDependent()
- { return CurrentObject(); }
- };
-
-
- class CNotifierIterator : public CDependencyIterator {
- public:
- CNotifierIterator (TObject* theObject, TSimpleDependencySpace* dependencySpace);
-
- virtual ~CNotifierIterator();
-
- inline TObject* FirstNotifier()
- { return FirstObject(); }
-
- inline TObject* NextNotifier()
- { return NextObject(); }
-
- inline TObject* CurrentNotifier()
- { return CurrentObject(); }
- };
-
- extern TDependencySpace* gMacAppDependencies;
-
- #endif // __UDEPENDENCIES__
-